import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sjm_lib/utils/utils_router.dart';
import 'package:sjm_lib/utils/utils_ui.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_android/webview_flutter_android.dart';
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';

const String ErrorPage = '''
    <!DOCTYPE html>
    <html lang="en">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, target-densitydpi=device-dpi" />
    <head>
    <title>出错了</title>
    </head>
    <body>
    <h2>页面打不开了</h2>
    </body>
    </html>
''';

class ComponentWebView extends StatefulWidget {
  final String? url;
  final String? htmlString;

  const ComponentWebView({this.url, this.htmlString, super.key});

  @override
  State<ComponentWebView> createState() => _ComponentWebViewState();
}

class _ComponentWebViewState extends State<ComponentWebView> {
  late final WebViewController _webViewController;
  late final WebViewCookieManager cookieManager = WebViewCookieManager();
  late final PlatformWebViewControllerCreationParams params;
  String _title = '';

  @override
  void initState() {
    UIUtil.showToastLoading();
    super.initState();
    if (WebViewPlatform.instance is WebKitWebViewPlatform) {
      params = WebKitWebViewControllerCreationParams(
        allowsInlineMediaPlayback: true,
        // mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
      );
    } else {
      params = const PlatformWebViewControllerCreationParams();
    }

    _webViewController = WebViewController.fromPlatformCreationParams(params);

    _webViewController
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(const Color(0x00000000))
      ..setNavigationDelegate(
        NavigationDelegate(
          onProgress: (int progress) {
            UIUtil.log("加载进度", progress);
          },
          onPageStarted: (String url) {
            UIUtil.log("开始", url);
          },
          onPageFinished: (String url) {
            _getWebTitle();
            UIUtil.log("加载完成", url);
            UIUtil.closeToastLoading();
          },
          onWebResourceError: (WebResourceError error) {
            UIUtil.log("失败了${error.errorCode}", error.description);
            UIUtil.log("失败了errorType", error.errorType);
            _onLoadHtmlStringExample(ErrorPage);
          },
          onNavigationRequest: (NavigationRequest request) async{
            String url = request.url;
            UIUtil.log("准备访问", request.url);
            if (url.startsWith('weixin://')) {
              UIUtil.log("阻塞访问", request.url);
              await UtilsNavigator.openLaunch(Uri.parse(url));
              UtilsNavigator.pop(context);
              return NavigationDecision.prevent;
            }

            UIUtil.log("允许访问", request.url);
            return NavigationDecision.navigate;
          },
          onUrlChange: (UrlChange change) async {
            UIUtil.log("链接变化", change.url);
            try {
              if (change.url!.startsWith('alipay://') || change.url!.startsWith('weixin://')) {
                await UtilsNavigator.openLaunch(Uri.parse(change.url!));
                UtilsNavigator.pop(context);
              }
            } finally {
              UIUtil.closeToastLoading();
            }
          },
        ),
      )
      ..addJavaScriptChannel(
        'WSToast',
        onMessageReceived: (JavaScriptMessage message) {
          UIUtil.log("接受到web发送来的数据", message.message);
        },
      );

    if (widget.htmlString != null) {
      _onLoadHtmlStringExample(widget.htmlString!).then((value) {});
    } else {
      _webViewController.loadRequest(Uri.parse(widget.url ?? ''));
    }

    // #docregion platform_features
    if (_webViewController.platform is AndroidWebViewController) {
      AndroidWebViewController.enableDebugging(true);
      (_webViewController.platform as AndroidWebViewController)
          .setMediaPlaybackRequiresUserGesture(false);
    }
  }

  _getWebTitle() async {
    _title = (await _webViewController.runJavaScriptReturningResult('document.title') as String)
        .replaceAll('"', '');
    setState(() {});
  }

  @override
  void dispose() {
    super.dispose();
    _webViewController.removeJavaScriptChannel('WSToast');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('详情'),
        actions: <Widget>[
          NavigationControls(webViewController: _webViewController),
        ],
      ),
      body: WebViewWidget(controller: _webViewController),
    );
  }

  Future<void> _onGetCurrentUrl() async {
    final String? url = await _webViewController.currentUrl();
  }

  Future<void> _onShowUserAgent() {
    return _webViewController.runJavaScript(
      'WSToast.postMessage("UserAgent: " + navigator.userAgent);',
    );
  }

  // 获取cookielist
  Future<void> _onListCookies(BuildContext context) async {
    final String cookies =
        await _webViewController.runJavaScriptReturningResult('document.cookie') as String;
  }

  Future<void> _onAddToCache(BuildContext context) async {
    await _webViewController.runJavaScript(
      'caches.open("test_caches_entry"); localStorage["test_localStorage"] = "dummy_entry";',
    );
    if (context.mounted) {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
        content: Text('Added a test entry to cache.'),
      ));
    }
  }

  Future<void> _onListCache() {
    return _webViewController.runJavaScript('caches.keys()'
        // ignore: missing_whitespace_between_adjacent_strings
        '.then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))'
        '.then((caches) => WSToast.postMessage(caches))');
  }

  Future<void> _onClearCache(BuildContext context) async {
    await _webViewController.clearCache();
    await _webViewController.clearLocalStorage();
    if (context.mounted) {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
        content: Text('清除缓存.'),
      ));
    }
  }

  // 清空cookie
  Future<void> _onClearCookies(BuildContext context) async {
    final bool hadCookies = await cookieManager.clearCookies();
  }

  Future<void> _onNavigationDelegateExample() {
    final String contentBase64 = base64Encode(
      const Utf8Encoder().convert(ErrorPage),
    );
    return _webViewController.loadRequest(
      Uri.parse('data:text/html;base64,$contentBase64'),
    );
  }

  Future<void> _onSetCookie() async {
    await cookieManager.setCookie(
      const WebViewCookie(
        name: ' ',
        value: '',
        domain: '',
      ),
    );
    await _webViewController.loadRequest(Uri.parse(
      '',
    ));
  }

  // 发送请求
  Future<void> _onDoPostRequest() {
    return _webViewController.loadRequest(
      Uri.parse(''),
      method: LoadRequestMethod.post,
      headers: <String, String>{'foo': 'bar', 'Content-Type': 'text/plain'},
      body: Uint8List.fromList('Test Body'.codeUnits),
    );
  }

  // 加载资源管理器里的html
  Future<void> _onLoadLocalFileExample() async {
    final String pathToIndex = await _prepareLocalFile();
    await _webViewController.loadFile(pathToIndex);
  }

  // 加载本地html
  Future<void> _onLoadFlutterAssetExample(path) {
    return _webViewController.loadFlutterAsset(path);
  }

  // 加载html字符窜
  Future<void> _onLoadHtmlStringExample(String path) {
    return _webViewController.loadHtmlString(path);
  }

  static Future<String> _prepareLocalFile() async {
    final String tmpDir = (await getTemporaryDirectory()).path;
    final File indexFile = File(<String>{tmpDir, 'www', 'index.html'}.join(Platform.pathSeparator));

    await indexFile.create(recursive: true);
    await indexFile.writeAsString(ErrorPage);

    return indexFile.path;
  }
}

class NavigationControls extends StatelessWidget {
  const NavigationControls({super.key, required this.webViewController});

  final WebViewController webViewController;

  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        IconButton(
          icon: const Icon(
            Icons.arrow_back_ios,
            size: 12,
          ),
          onPressed: () async {
            if (await webViewController.canGoBack()) {
              await webViewController.goBack();
            } else {
              if (context.mounted) {
                UIUtil.showToast("没有历史");
              }
            }
          },
        ),
        IconButton(
          icon: const Icon(
            Icons.arrow_forward_ios,
            size: 12,
          ),
          onPressed: () async {
            if (await webViewController.canGoForward()) {
              await webViewController.goForward();
            } else {
              if (context.mounted) {
                UIUtil.showToast("没有更多");
              }
            }
          },
        ),
        IconButton(
          icon: const Icon(
            Icons.replay,
            size: 12,
          ),
          onPressed: () => webViewController.reload(),
        ),
      ],
    );
  }
}
